/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.hsrm;

import com.sun.spot.io.j2me.radiogram.Radiogram;
import com.sun.spot.io.j2me.radiogram.RadiogramConnection;
import java.io.IOException;
import javax.microedition.io.Connector;

/**
 *
 * @author acme
 */
public class CoordinatorSendThread extends Thread {
    
    
//    private final int SOUTH = 0;
//    private final int EAST = 1;
//    private final int NORTH = 2;
//    private final int WEST = 3;
//    private final int LEFT = 0;
//    private final int MIDDLE = 1;
//    private final int RIGHT = 2;
    public boolean threadON = true;
    
//    //possible combinations
//    private final int[][][] greenCombinations = 
//    {
//        {
//            {EAST, LEFT}, {EAST, MIDDLE}, {NORTH, MIDDLE}, {NORTH, RIGHT}, {WEST, LEFT}, {WEST, MIDDLE}
//        },
//        {
//            {EAST, LEFT}, {EAST, MIDDLE}, {EAST, RIGHT}, {NORTH, LEFT}, {WEST, LEFT}, {WEST, MIDDLE}
//        },
//        {
//            {SOUTH, MIDDLE}, {SOUTH, RIGHT}, {EAST, MIDDLE}, {EAST, RIGHT}, {WEST, MIDDLE}, {WEST, RIGHT}
//        },
//        {
//            {SOUTH, LEFT}, {SOUTH, MIDDLE}, {EAST, MIDDLE}, {EAST, RIGHT}, {NORTH, RIGHT}, {WEST, LEFT}
//        },
//        {
//            {SOUTH, MIDDLE}, {SOUTH, RIGHT}, {EAST, LEFT}, {EAST, MIDDLE}, {WEST, LEFT}, {WEST, MIDDLE}
//        },
//        {
//            {SOUTH, LEFT}, {EAST, LEFT}, {EAST, MIDDLE}, {WEST, LEFT}, {WEST, MIDDLE}, {WEST, RIGHT}
//        },
//        {
//             {SOUTH, LEFT}, {SOUTH, MIDDLE}, {EAST, MIDDLE}, {EAST, RIGHT}, {NORTH, LEFT}, {NORTH, MIDDLE}
//        },
//        {
//            {SOUTH, LEFT}, {SOUTH, MIDDLE}, {EAST, LEFT}, {EAST, MIDDLE}, {NORTH, LEFT}, {NORTH, MIDDLE}
//        }
//            
//    };
    
    private int[][] laneArray = {
                                    {0,0}, {0,1}, {0,2},
                                    {1,0}, {1,1}, {1,2},
                                    {2,0}, {2,1}, {2,2},
                                    {3,0}, {3,1}, {3,2}
                                };
    private int[] laneWeights = new int[12];
    
    private final int[][] greenCombos =
    {
        {0,1,2,11},
        {3,4,5,2},
        {6,7,8,5},
        {9,10,11,8},
        {1,2,7,8},
        {4,5,10,11},
        {0,5,6,11},
        {3,8,9,2},
        {1,2,8,11},
        {4,5,11,2},
        {7,8,2,5},
        {10,11,5,8}
    };
    
    RadiogramConnection tx = null;
    Radiogram xdg;
    
    public CoordinatorSendThread()
    {
        
    }
    
    public void run(){
        int currentLane = 0;
        try
        {
            while(threadON)
            {
                sendRedSignal();
                sleep(Util.RED_TIME);
                updateTable();
                sleep(Util.CHECK_TIMEOUT);
                currentLane = getGreenLane();
                System.out.println("\nMaxLane: "
                         + String.valueOf(currentLane));
                if(currentLane != -1)
                {
                    sendGreenSignal(currentLane);
                    //updateWaitTime(currentLane);
                }
                sleep(Util.GREEN_TIME);
                
                
            }          
            
        } catch (Exception ex) {
           
        }
    
    }
    
    private void updateTable()
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                for (int k = 0; k < Util.MAX_ADRESSES; k++)
                {
                    if(AddressTable.getInstance().getCar((10000 + i*1000 + j*100 + k)) != null)
                        if(!AddressTable.getInstance().getCar((10000 + i*1000 + j*100 + k)).isChecked())
                            AddressTable.getInstance().deleteAddressTableEntry((10000 + i*1000 + j*100 + k));
                    
                }
            }
        }
    }
    
//    private int getMinLane()
//    {
//        int minLane = -1;
//        int minLaneWeight = 0;
//        int currentLaneWeight = 0;
//        for (int i = 0; i < greenCombinations.length; i++)
//        {
//            for (int j = 0; j < greenCombinations[i].length; j++)
//            {
//                currentLaneWeight -= 
//                        AddressTable.getInstance().getLaneWaitTime(greenCombinations[i][j][0], greenCombinations[i][j][1]);
//            }
//            if(currentLaneWeight < minLaneWeight)
//            {
//                minLaneWeight = currentLaneWeight;
//                minLane = i;
//            }
//            currentLaneWeight = 0;
//        }
//               
//        return minLane;       
//    }
    
    private int getGreenLane()
    {
        int greenLane = -1;
        int currentWaitTime = 0;
        int maxWaitTime = 0;
        
        for(int i = 0; i < laneWeights.length; i++)
        {
            laneWeights[i] = AddressTable.getInstance().getLaneWaitTime(laneArray[i][0], laneArray[i][1]);
        }
        
        for (int i = 0; i < greenCombos.length; i++)
        {
            for (int j = 0; j < greenCombos[i].length; j++)
            {
                currentWaitTime = currentWaitTime + laneWeights[greenCombos[i][j]];
            }
            if(currentWaitTime > maxWaitTime)
            {
                maxWaitTime = currentWaitTime;
                greenLane = i;
            }
            currentWaitTime = 0;
        }
        
        return greenLane;
    }
    
    private synchronized void sendGreenSignal(int maxLane)
    {
        try {
            tx = (RadiogramConnection)Connector.open("radiogram://broadcast:123");
            xdg = (Radiogram)tx.newDatagram(tx.getMaximumLength());
            
            int location = 0;
            int lane = 0;            
            
            for(int i = 0; i < greenCombos[maxLane].length; i++)
            {
                location = laneArray[greenCombos[maxLane][i]][0];
                lane = laneArray[greenCombos[maxLane][i]][1];
                sendMessage(Address.COORDINATOR,
                            (10000 + location*1000 + lane*100),
                            MsgType.SIGNAL,
                            Sequence.getSeqNr(),
                            0,
                            SignalColor.GREEN);
                try{
                    sleep(20);
                } catch (Exception ex) {

                }
            }            
           
        } catch (IOException ex) {
            System.out.println("Error opening connections: " + ex);
            ex.printStackTrace();
        }
    }
    
    private synchronized void sendRedSignal()
    {
        try {
            tx = (RadiogramConnection)Connector.open("radiogram://broadcast:123");
            xdg = (Radiogram)tx.newDatagram(tx.getMaximumLength());
            
            boolean green = true;
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    for (int k = 0; k < Util.MAX_ADRESSES; k++)
                    {
                        if(AddressTable.getInstance().getCar((10000 + i*1000 + j*100 + k)) != null)
                            AddressTable.getInstance().getCar((10000 + i*1000 + j*100 + k)).setChecked(false);
                    }  
                    sendMessage(Address.COORDINATOR,
                                (10000 + i*1000 + j*100),
                                MsgType.SIGNAL,
                                Sequence.getSeqNr(),
                                0,
                                SignalColor.RED);
                    try{
                        sleep(20);
                    } catch (Exception ex) {

                    }
                    
                }
            }
        } catch (IOException ex) {
            System.out.println("Error opening connections: " + ex);
            ex.printStackTrace();
        }
    }
    
    protected synchronized void updateWaitTime(int maxLane)
    {
        
        int location = 0;
        int lane= 0;
        for(int i = 0; i < greenCombos[maxLane].length; i++)
            {
                location = laneArray[greenCombos[maxLane][i]][0];
                lane = laneArray[greenCombos[maxLane][i]][1];
                AddressTable.getInstance().updateLaneWaitTime(location, lane);
        }
        
    }
    
    protected synchronized void sendMessage(int msgSource, int msgDest, int msgType, int msgSeqNr, int assignedAddr, int data)
    {
        try {
                      
            xdg.reset();
            
            xdg.writeInt(msgSource);
            xdg.writeInt(msgDest);
            xdg.writeInt(msgType);
            xdg.writeInt(msgSeqNr);
            xdg.writeInt(assignedAddr);
            xdg.writeInt(data);
            tx.send(xdg);
            
            if(msgType == MsgType.SIGNAL)
            {    
                System.out.println("\nSignal Sent:\n"
                        + "\ndest: " + String.valueOf(msgDest)
                        + "\nSignal: " + String.valueOf(data));
            }
            
            } catch (IOException ex){
            System.out.println("Error sending packet: " + ex);
            ex.printStackTrace();
        }
    }
    
}
